import pygame
from OpenGL.GL import *
import math
from geometry import normal

class OBJ:
	def __init__(self, filename, swapyz=False):
		"""Loads a Wavefront OBJ file. """
		self.vertices = []
		self.normals = []
		self.faces = []
		print "loading file",filename
		for line in open(filename, "r"):
			if line.startswith('#'): continue
			values = line.split()
			if not values: continue
			if values[0] == 'v':
				v = map(float, values[1:4])
				if swapyz:
					v = v[0], v[2], v[1]
				self.vertices.append(v)
			elif values[0] == 'vn':
				v = map(float, values[1:4])
				if swapyz:
					v = v[0], v[2], v[1]
				self.normals.append(v)
			elif values[0] == 'f':
				face = []
				norms = []
				for v in values[1:]:
					w = v.split('/')
					face.append(int(w[0]))
					if len(w) >= 3 and len(w[2]) > 0:
						norms.append(int(w[2]))
					else:
						norms.append(0)
				self.faces.append((face, norms))
	
		if len(self.normals)==0:
			print "Generating normals"
			for i,f in enumerate(self.faces):
				verts, norms = f
				n = normal(self.vertices[verts[0]-1],self.vertices[verts[1]-1],self.vertices[verts[2]-1])
				self.normals.append(n)
				norms = (len(self.normals),)*3
				self.faces[i] = verts,norms

		print "Centering mesh"
		minv = list(self.vertices[0])
		maxv = minv[:]
		for v in self.vertices:
			for i in range(3):
				if minv[i]>v[i]:
					minv[i] = v[i]	
				if maxv[i]<v[i]:
					maxv[i] = v[i]
		cv = tuple([(minv[i]+maxv[i])/2 for i in range(3)])

		for i,v in enumerate(self.vertices):
			self.vertices[i] = tuple([a-b for a,b in zip(v,cv)])

		print "Bounding box:"
		self.minv = tuple([a-b for a,b in zip(minv,cv)])
		self.maxv = ([a-b for a,b in zip(maxv,cv)])
		print self.minv
		print self.maxv

		print "Faces: ",len(self.faces)
		print "Vertices: ",len(self.vertices)

		sc = max(self.maxv[0],self.maxv[2])
		if sc>1:
			print "Scaling to <1 max size"
			for i,v in enumerate(self.vertices):
				self.vertices[i] = tuple([a/sc for a in v])
			for i in range(3):
				maxv[i] /= sc
				minv[i] /= sc
		print "Now bounding is:"
		print minv
		print maxv
		self.minv = minv
		self.maxv = maxv
		
	def genlist(self):
		minv = self.minv
		maxv = self.maxv
		print "Generating display list"
		self.gl_list = glGenLists(1)
		glNewList(self.gl_list, GL_COMPILE)
		glEnable(GL_TEXTURE_2D)
		glFrontFace(GL_CCW)
		for face in self.faces:
			vertices, normals = face
			glBegin(GL_POLYGON)
			for i in range(len(vertices)):
				try:
					if normals[i] > 0:
						glNormal3fv(self.normals[normals[i] - 1])
				except IndexError:
					glNormal3fv(self.normals[normals[0]-1])
				glVertex3fv(self.vertices[vertices[i] - 1])
			glEnd()
		glDisable(GL_TEXTURE_2D)
		glEndList()

		self.bounding_list = glGenLists(1)
		glNewList(self.bounding_list,GL_COMPILE)
		glDisable(GL_LIGHTING)
		glBegin(GL_LINES)
		glVertex(minv[0],minv[0],minv[0])
		glVertex(maxv[0],minv[0],minv[0])

		glVertex(maxv[0],minv[0],minv[0])
		glVertex(maxv[0],maxv[0],minv[0])

		glVertex(maxv[0],maxv[0],minv[0])
		glVertex(minv[0],maxv[0],minv[0])

		glVertex(minv[0],maxv[0],minv[0])
		glVertex(minv[0],minv[0],minv[0])

		glVertex(minv[0],minv[0],maxv[0])
		glVertex(maxv[0],minv[0],maxv[0])

		glVertex(maxv[0],minv[0],maxv[0])
		glVertex(maxv[0],maxv[0],maxv[0])

		glVertex(maxv[0],maxv[0],maxv[0])
		glVertex(minv[0],maxv[0],maxv[0])

		glVertex(minv[0],maxv[0],maxv[0])
		glVertex(minv[0],minv[0],maxv[0])

		glVertex(minv[0],minv[0],maxv[0])
		glVertex(minv[0],minv[0],minv[0])

		glVertex(maxv[0],minv[0],maxv[0])
		glVertex(maxv[0],minv[0],minv[0])

		glVertex(maxv[0],maxv[0],maxv[0])
		glVertex(maxv[0],maxv[0],minv[0])

		glVertex(minv[0],maxv[0],maxv[0])
		glVertex(minv[0],maxv[0],minv[0])

		glEnd()
		glEnable(GL_LIGHTING)
		glEndList()
		print "Ready!"
